﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;

using FingerPrint.WebUI.Abstract;
//using FingerPrint.WebUI.Concrete;
using FingerPrint.WebUI.Models;
using FingerPrint.WebUI.ViewModels;
using FingerPrint.WebUI.DAL;
using Kendo.Mvc.UI;
using Kendo.Mvc.Extensions;


namespace FingerPrint.WebUI.Controllers
{
    public class SalesOrderController : Controller
    {
        //private ISalesOrderRepository repository;

        //public SalesOrderController(ISalesOrderRepository SalesOrderRepository)
        //{
        //    repository = SalesOrderRepository;
        //}

        //Trying to use unitofwork, the following will be disabled
        FingerPrintContext db = new FingerPrintContext();

        private UnitOfWork unitOfWork = new UnitOfWork();


        //#region SalesOrder

        // GET: /SalesOrder/ (for Kendo UI Grid)
        public ViewResult Index()
        {
            PopulateEmployees();                            // Populate a list of employees to be used in Filter
            return View(GetAllSalesOrders().ToList());
        }


        // datasource in JSON format (for Kendo UI Grid)
        public ActionResult Read([DataSourceRequest] DataSourceRequest request)
        {
            PopulateEmployees(); 
            return Json(GetAllSalesOrders().ToDataSourceResult(request));
        }


        // GET: /SalesOrder/Details/5
        public ViewResult Details(int id)
        {
            SalesOrder salesorder = unitOfWork.SalesOrderRepository.GetByID(id);
            return View(salesorder);
        }


        // GET: /SalesOrder/Create
        public ActionResult Create()
        {
            PopulateEmployeesDropDownList();
            return View();
        }

        [HttpPost]
        public ActionResult Create(SalesOrder salesorder)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    unitOfWork.SalesOrderRepository.Insert(salesorder);
                    unitOfWork.Save();
                    return RedirectToAction("Index");
                }
            }
            catch (DataException)
            {
                //Log the error (add a variable name after DataException)
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
            }
            PopulateEmployeesDropDownList(salesorder.EmployeeID);
            PopulateCustomersDropDownList(salesorder.CustomerID);
            return View(salesorder);
        }


        // GET: /SalesOrder/Edit/5
        public ActionResult Edit(int id)
        {
            SalesOrder salesOrder = unitOfWork.SalesOrderRepository.GetByID(id);

            PlaceProductGroupToViewBag(salesOrder);
            PlaceProductCategoryToViewBag(salesOrder);
            PopulateSelectedProductData(salesOrder);
            PopulateEmployeesDropDownList(salesOrder.EmployeeID);
            PopulateCustomersDropDownList(salesOrder.CustomerID);

            return View(salesOrder);
        }

        //
        // POST: /SalesOrder/Edit/5
        [HttpPost]
        public ActionResult Edit(SalesOrder salesOrder)
        {
            try
            {

                if (ModelState.IsValid)
                {
                    unitOfWork.SalesOrderRepository.Update(salesOrder);
                    unitOfWork.Save();
                    //db.Entry(salesorder).State = EntityState.Modified;
                    //db.SaveChanges();
                    return RedirectToAction("Index");
                }
            }
            catch (DataException)
            {
                //Log the error (add a variable name after DataException)
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
            }
            PopulateEmployeesDropDownList(salesOrder.EmployeeID);
            PopulateCustomersDropDownList(salesOrder.CustomerID);
            return View(salesOrder);
            
        }



        // GET: /SalesOrder/Delete/5
        public ActionResult Delete(int id)
        {
            SalesOrder salesorder = unitOfWork.SalesOrderRepository.GetByID(id);
            return View(salesorder);
        }

        //
        // POST: /SalesOrder/Delete/5
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            SalesOrder salesorder = unitOfWork.SalesOrderRepository.GetByID(id);
            unitOfWork.SalesOrderRepository.Delete(id);
            unitOfWork.Save();
            return RedirectToAction("Index");
        }


        protected override void Dispose(bool disposing)
        {
            unitOfWork.Dispose();
            base.Dispose(disposing);
        }



// -----------------------------
// --- Functions and Methods ---
// -----------------------------

        // Populate the list of Employees
        private void PopulateEmployeesDropDownList(object selectedEmployee = null)
        {
            var employeesQuery = unitOfWork.EmployeeRepository.Get(
                orderBy: q => q.OrderBy(d => d.EngName));
            ViewBag.EmployeeID = new SelectList(employeesQuery, "EmployeeID", "EngName", selectedEmployee);
        }


        // Populate the list of Customers
        private void PopulateCustomersDropDownList(object selectedCustomer = null)
        {
            var customersQuery = unitOfWork.CustomerRepository.Get(
                orderBy: q => q.OrderBy(d => d.CompanyCode));
            ViewBag.CustomerID = new SelectList(customersQuery, "CustomerID", "CompanyCode", selectedCustomer);
        }

        // ---------------------------------------------------------------------------------------------
        // Method and match the model to entity
        
        // Method 1
        //private static IEnumerable<SalesOrderModel> GetAllSalesOrders()
        //{
        //    var db = new FingerPrintContext();

        //    var allSalesOrders = db.SalesOrders.Include("Employee").Select(so => new SalesOrderModel
        //        {
        //            SalesOrderID = so.SalesOrderID,
        //            SalesOrderNumber = so.SalesOrderNumber,
        //            ReceivedDate = so.ReceivedDate,

        //            EmployeeID = so.EmployeeID, //so.EmployeeID ?? 0,
        //            Employee = so.Employee,

        //            CustomerID = so.CustomerID,
        //            Deadline = so.Deadline,
        //            InvoiceNumber = so.InvoiceNumber,
        //            Remark = so.Remark,
        //            Status = so.Status,
        //            ModifiedDate = so.ModifiedDate
        //        });

        //    return (allSalesOrders);

        //}

        // Method 2
        private IEnumerable<SalesOrderModel> GetAllSalesOrders()
        {
            var allSalesOrders = unitOfWork.SalesOrderRepository
                    .Get(includeProperties: "Employee, Customer")
                    .Select(so => new SalesOrderModel
                    {
                        SalesOrderID = so.SalesOrderID,
                        SalesOrderNumber = so.SalesOrderNumber,
                        ReceivedDate = so.ReceivedDate,

                        //EmployeeID = so.EmployeeID, //so.EmployeeID ?? 0,
                        Employee = so.Employee,
                        Customer = so.Customer,

                        //CustomerID = so.CustomerID,
                        Deadline = so.Deadline,
                        InvoiceNumber = so.InvoiceNumber,
                        Remark = so.Remark,
                        Status = so.Status,
                        ModifiedDate = so.ModifiedDate
                    })
                    .OrderByDescending(so => so.SalesOrderID);
        return (allSalesOrders);
        }

        // The selected product in one SalesOrder
        private void PopulateSelectedProductData(SalesOrder salesOrder)
        {
            var allProducts = db.Products;
            var salesOrderProducts = new HashSet<int>(salesOrder.Products.Select(p => p.ProductID));

            var viewModel = new List<SelectedSalesOrderProducts>();
            foreach (var product in allProducts)
            {
                viewModel.Add(new SelectedSalesOrderProducts
                {
                    ProductID = product.ProductID,
                    Description = product.Description,
                    ProductCategoryID = product.ProductCategoryID,
                    ProductGroupID = product.ProductGroupID,
                    GroupNumber = product.ProductGroup.GroupNumber,

                    Selected = salesOrderProducts.Contains(product.ProductID)
                });
            }
            ViewBag.Products = viewModel;
        }


        private void PlaceProductCategoryToViewBag(SalesOrder salesOrder)
        {
            var allProductCategory = db.ProductCategories;
            var viewModel = new List<ProductCategoryViewModel>();

            foreach (var productCategory in allProductCategory)
            {
                viewModel.Add(new ProductCategoryViewModel
                {
                    ProductCategoryID = productCategory.ProductCategoryID,
                    Name = productCategory.Name,
                    Code = productCategory.Code,
                    Type = productCategory.Type
                });
            }
            ViewBag.ProductCategories = viewModel;
        }

        private void PlaceProductGroupToViewBag(SalesOrder salesOrder)
        {
            var allProductGroups = db.ProductGroups;
            var viewModel = new List<ProductGroupViewModel>();

            foreach (var productGroup in allProductGroups)
            {
                viewModel.Add(new ProductGroupViewModel
                {
                    ProductGroupID = productGroup.ProductGroupID,
                    GroupNumber = productGroup.GroupNumber,
                    Name = productGroup.Name,
                    ProductCategoryID = productGroup.ProductCategoryID
                });
            }
            ViewBag.ProductGroups = viewModel;
        }

        // Being Tested
        // Function to populate a list of Employees
        private void PopulateEmployees()
        {
            var employees = unitOfWork.EmployeeRepository
                .Get()
                .Select(e => new EmployeeViewModel
                {
                    EmployeeID = e.EmployeeID,
                    EmployeeName = e.EngName
                })
                .OrderBy(e => e.EmployeeName);

            ViewData["employees"] = employees;
            ViewData["defaultEmployees"] = employees.First();
        }

        // -----------------------------------------------------------------------------------------------------------------------

        //public int PageSize = 99;


        //public ViewResult List(int employeeID = 2, int page = 1)
        //{
        //    SalesOrdersListViewModel viewModel = new SalesOrdersListViewModel
        //    {
        //        SalesOrders = repository.SalesOrders
        //            .Where(s => employeeID == null || s.EmployeeID == employeeID)
        //            .OrderBy(s => s.SalesOrderID)
        //            .Skip((page - 1) * PageSize)
        //            .Take(PageSize),

        //        PagingInfo = new PagingInfo
        //        {
        //            CurrentPage = page,
        //            ItemsPerPage = PageSize,
        //            TotalItems = 10
        //            //TotalItems = employeeID == null ? 
        //            //        repository.SalesOrders.Count() :
        //            //        repository.SalesOrders.Where(e => e.EmployeeID == employeeID).Count()
        //        },

        //        CurrentEmployeeID = employeeID
        //    };
        //    return View(viewModel);
        //}
    }

    
}
